﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using myFinance.Models;

namespace myFinance.BLL
{
    public class PessoaBll
    {
        public static readonly Container db = new Container();

        /// <summary>
        /// Faz uma pesquisa e retorna a Pessoa pelo nome de Usuário
        /// </summary>
        /// <param name="db">Container</param>
        /// <param name="usuario">String</param>
        /// <returns>Pessoa</returns>
        public static Pessoa GetPessoa(string usuario)
        {
            return db.Pessoa.FirstOrDefault(f => f.Usuario == usuario);
        }

        /// <summary>
        /// Faz uma pesquisa e retorna a Pessoa pelo Id
        /// </summary>
        /// <param name="db">Container</param>
        /// <param name="id">Int</param>
        /// <returns>Pessoa</returns>
        public static Pessoa GetPessoa(int id)
        {
            return db.Pessoa.FirstOrDefault(f => f.Id == id);
        }

		/// <summary>
		/// Retorna o id da pessoa
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="usuario">String</param>
		/// <returns>Int</returns>
		public static int GetId(string usuario)
		{
			return db.Pessoa.Where(w => w.Usuario == usuario).Select(s => s.Id).FirstOrDefault();
		}

        public static Pessoa GetPessoaByFacebook_userID(int facebook_userID)
        {
            return db.Pessoa.FirstOrDefault(f => f.facebook_userID == facebook_userID);
        }

        public static bool ExisteUsuario(string usuario)
        {
            return db.Pessoa.FirstOrDefault(f => f.Usuario == usuario) != null;
        }

        /// <summary>
        /// Retorna um array de Bytes (byte[]) com as informações da imagem do avatar de acordo com o nome de Usuário
        /// </summary>
        /// <param name="db">Container</param>
        /// <param name="usuario">String</param>
        /// <returns>Byte[]</returns>
        public static Byte[] GetAvatar(string usuario)
        {
            return db.Pessoa.Where(w => w.Usuario == usuario).Select(s => s.Avatar).FirstOrDefault();
        }

        /// <summary>
        /// Grava a Pessoa no banco de dados
        /// </summary>
        /// <param name="db">Container</param>
        /// <param name="p">Pessoa</param>
        /// <returns>Boolean</returns>
        public static bool Add(Pessoa p)
        {
            try
            {
				db.Connection.Open();
				using (var transaction = db.Connection.BeginTransaction())
				{
					try
					{
						db.Pessoa.AddObject(p);
                        db.SaveChanges();

						// GRUPOS DE DESPESAS: 
						// Alimentos, Básicos, Contornáveis e Dispensáveis

						// SUB-GRUPOS DE DESPESAS: 
						// Alimentos = Mercado, Padaria, Acougue
						// Basicos = Aluguel, Agua e Esgoto, Eletricidade, Gas, Materiais de Limpeza
						// Contornaveis = Combustivel, Manutenção do Carro, Manutencao da Casa
						// Dispensáveis = Cinema, Restaurante, Happy Hour, Lanchonete, Presentes

                        var idPessoa = p.Id;

						// INCLUI OS GRUPOS DE DESPESA
						#region Alimentos
						var gp1 = new GrupoDespesa();
						gp1.PessoaId = idPessoa;
						gp1.Nome = "Alimentos";
						db.GrupoDespesa.AddObject(gp1);
						#endregion

						#region Básicos
						var gp2 = new GrupoDespesa();
						gp2.PessoaId = idPessoa;
						gp2.Nome = "Básicos";
						db.GrupoDespesa.AddObject(gp2);
						#endregion

						#region Contornáveis
						var gp3 = new GrupoDespesa();
						gp3.PessoaId = idPessoa;
						gp3.Nome = "Contornáveis";
						db.GrupoDespesa.AddObject(gp3);						
						#endregion

						#region Dispensáveis
						var gp4 = new GrupoDespesa();
						gp4.PessoaId = idPessoa;
						gp4.Nome = "Dispensáveis";
						db.GrupoDespesa.AddObject(gp4);						
						#endregion

						db.SaveChanges();
						
						// INCLUI OS SUB-GRUPOS DE DESPESA
						#region Alimentos > Sub-Grupos
						var sgpMercado = new SubGrupoDespesa();
						sgpMercado.GrupoDespesaId = gp1.Id;
						sgpMercado.Nome = "Mercado";
						db.SubGrupoDespesa.AddObject(sgpMercado);

						var sgpPadaria = new SubGrupoDespesa();
						sgpPadaria.GrupoDespesaId = gp1.Id;
						sgpPadaria.Nome = "Padaria";
						db.SubGrupoDespesa.AddObject(sgpPadaria);

						var sgpAcougue = new SubGrupoDespesa();
						sgpAcougue.GrupoDespesaId = gp1.Id;
						sgpAcougue.Nome = "Açougue";
						db.SubGrupoDespesa.AddObject(sgpAcougue);
						#endregion						

						#region Básicos > Sub-Grupos
						var sgpAluguel = new SubGrupoDespesa();
						sgpAluguel.GrupoDespesaId = gp2.Id;
						sgpAluguel.Nome = "Aluguel";
						db.SubGrupoDespesa.AddObject(sgpAluguel);

						var sgpAgua = new SubGrupoDespesa();
						sgpAgua.GrupoDespesaId = gp2.Id;
						sgpAgua.Nome = "Água e Esgoto";
						db.SubGrupoDespesa.AddObject(sgpAgua);

						var sgpEletricidade = new SubGrupoDespesa();
						sgpEletricidade.GrupoDespesaId = gp2.Id;
						sgpEletricidade.Nome = "Eletricidade";
						db.SubGrupoDespesa.AddObject(sgpEletricidade);

						var sgpGas = new SubGrupoDespesa();
						sgpGas.GrupoDespesaId = gp2.Id;
						sgpGas.Nome = "Gás";
						db.SubGrupoDespesa.AddObject(sgpGas);

						var sgpMateriais = new SubGrupoDespesa();
						sgpMateriais.GrupoDespesaId = gp2.Id;
						sgpMateriais.Nome = "Materiais de Limpeza";
						db.SubGrupoDespesa.AddObject(sgpMateriais);
						#endregion

						#region Contornáveis > Sub-Grupos
						var sgpCombustivel = new SubGrupoDespesa();
						sgpCombustivel.GrupoDespesaId = gp3.Id;
						sgpCombustivel.Nome = "Combustíveis";
						db.SubGrupoDespesa.AddObject(sgpCombustivel);

						var sgpManutencaoCarro = new SubGrupoDespesa();
						sgpManutencaoCarro.GrupoDespesaId = gp3.Id;
						sgpManutencaoCarro.Nome = "Manutenção do Carro";
						db.SubGrupoDespesa.AddObject(sgpManutencaoCarro);

						var sgpManutencaoCasa = new SubGrupoDespesa();
						sgpManutencaoCasa.GrupoDespesaId = gp3.Id;
						sgpManutencaoCasa.Nome = "Manutenção da Casa";
						db.SubGrupoDespesa.AddObject(sgpManutencaoCasa);
						#endregion

						#region Dispensáveis > Sub-Grupos
						var sgpCinema = new SubGrupoDespesa();
						sgpCinema.GrupoDespesaId = gp4.Id;
						sgpCinema.Nome = "Cinema";
						db.SubGrupoDespesa.AddObject(sgpCinema);

						var sgpRestaurante = new SubGrupoDespesa();
						sgpRestaurante.GrupoDespesaId = gp4.Id;
						sgpRestaurante.Nome = "Restaurante";
						db.SubGrupoDespesa.AddObject(sgpRestaurante);

						var sgpHappy = new SubGrupoDespesa();
						sgpHappy.GrupoDespesaId = gp4.Id;
						sgpHappy.Nome = "Happy Hour";
						db.SubGrupoDespesa.AddObject(sgpHappy);

						var sgpLanchonete = new SubGrupoDespesa();
						sgpLanchonete.GrupoDespesaId = gp4.Id;
						sgpLanchonete.Nome = "Lanchonete";
						db.SubGrupoDespesa.AddObject(sgpLanchonete);

						var sgpPresentes = new SubGrupoDespesa();
						sgpPresentes.GrupoDespesaId = gp4.Id;
						sgpPresentes.Nome = "Presentes";
						db.SubGrupoDespesa.AddObject(sgpPresentes);
						#endregion

						db.SaveChanges();
						transaction.Commit();
						return true;
					}
					catch (Exception ex)
					{
						throw ex;
					}
					finally
					{
						db.Connection.Close();
					}
				}
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Altera a Pessoa no banco de dados
        /// </summary>
        /// <param name="db">Container</param>
        /// <param name="p">Pessoa</param>
        /// <returns>Boolean</returns>
        public static bool Edit(Pessoa p)
        {
            try
            {
                db.Pessoa.ApplyCurrentValues(p);
                db.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Exclui uma Pessoa do banco de dados
        /// </summary>
        /// <param name="db">Container</param>
        /// <param name="p">Pessoa</param>
        /// <returns>Boolean</returns>
        public static bool Delete(int id)
        {
            try
            {
                var p = db.Pessoa.FirstOrDefault(f => f.Id == id);
                db.Pessoa.DeleteObject(p);
                db.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Faz a validação do CPF
        /// </summary>
        /// <param name="cpf">String</param>
        /// <returns>Boolean</returns>
        public static bool ValidarCPF(string cpf)
        {
            if (string.IsNullOrWhiteSpace(cpf.Trim()))
            {
                return true;
            }
            else
            {
                int[] multiplicador1 = new int[9] { 10, 9, 8, 7, 6, 5, 4, 3, 2 };
                int[] multiplicador2 = new int[10] { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 };
                string tempCpf;
                string digito;
                int soma;
                int resto;

                cpf = cpf.Trim();
                cpf = cpf.Replace(".", "").Replace("-", "");

                if (cpf.Length != 11)
                    return false;

                switch (cpf)
                {
                    case "11111111111":
                        return false;
                    case "00000000000":
                        return false;
                    case "22222222222":
                        return false;
                    case "33333333333":
                        return false;
                    case "44444444444":
                        return false;
                    case "55555555555":
                        return false;
                    case "66666666666":
                        return false;
                    case "77777777777":
                        return false;
                    case "88888888888":
                        return false;
                    case "99999999999":
                        return false;
                }

                tempCpf = cpf.Substring(0, 9);
                soma = 0;
                for (int i = 0; i < 9; i++)
                    soma += int.Parse(tempCpf[i].ToString()) * multiplicador1[i];

                resto = soma % 11;
                if (resto < 2)
                    resto = 0;
                else
                    resto = 11 - resto;

                digito = resto.ToString();

                tempCpf = tempCpf + digito;

                soma = 0;
                for (int i = 0; i < 10; i++)
                    soma += int.Parse(tempCpf[i].ToString()) * multiplicador2[i];

                resto = soma % 11;
                if (resto < 2)
                    resto = 0;
                else
                    resto = 11 - resto;

                digito = digito + resto.ToString();

                return cpf.EndsWith(digito);
            }
        }
    }
}